use std::{rc::Rc, cell::RefCell};

use crate::{rtda::Frame, instructions::base::{Instruction, BytecodeReader}};


// iload指令的索引来自操作数，其他来自指令
// Load int from local variable
#[derive(Debug, Default)]
pub struct ILOAD {
    index: usize
}

impl Instruction for ILOAD {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u8() as usize;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _iload(frame, self.index);
    }
}

impl ILOAD {
    pub fn set_index(&mut self, index: usize) {
        self.index = index;
    } 
}

#[derive(Debug, Default)]
pub struct ILOAD_0 { }

impl Instruction for ILOAD_0 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _iload(frame, 0);
    }
}

#[derive(Debug, Default)]
pub struct ILOAD_1 { }

impl Instruction for ILOAD_1 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _iload(frame, 1);
    }
}

#[derive(Debug, Default)]
pub struct ILOAD_2 { }

impl Instruction for ILOAD_2 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _iload(frame, 2);
    }
}

#[derive(Debug, Default)]
pub struct ILOAD_3 { }

impl Instruction for ILOAD_3 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _iload(frame, 3);
    }
}

// 通用加载，从局部变量表获取变量，推入操作数栈顶
fn _iload(frame: Rc<RefCell<Frame>>, index: usize) {
    let val = frame.borrow().get_local_vars().borrow().get_int(index);
    frame.borrow().get_operand_stack().borrow_mut().push_int(val);
}